/*
 * =====================================================================================
 *
 *       Filename:  configer.h
 *
 *    Description:  .conf file read and write
 *
 *        Version:  1.0
 *        Created:  2013年05月17日 10时40分17秒
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Wu Yuxin
 *        Company:  www.Qihoo.net
 *
 * =====================================================================================
 */

#include <stdint.h>
#include <map>
#include <string>
#include <fstream>
#include <sstream>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>

namespace act {

  typedef std::map<std::string, int64_t> map_string;

  class config {
    private:
      map_string pair_;
      std::string file_;
      bool read_;
    public:
      config(const std::string& f) : file_(f), read_(false) {}
      ~config() { save(); }

      int64_t reset(const std::string& key, const int64_t step) {
        if (!read_)
          read(step);
        int64_t r = step;
        map_string::iterator it = pair_.find(key);
        if (it != pair_.end()) {
          r = it->second;
          int64_t w = r + step;
          it->second = w;
        } else {
          r = 0;
          pair_[key] = r + step;
        }

        save();
        return r;
      }

    private:
      config& read(const int64_t step) {
        std::fstream f(file_.c_str());
        std::string l, k, v;
        if (f.is_open()) {
          while (std::getline(f, l)) {
            boost::trim(l);
            if (l.empty() || (';'==l[0]) || ('#'==l[0])) continue;

            std::string::size_type p = l.find('=');
            if (std::string::npos != p) {
              k = l.substr(0, p);
              boost::trim(k);
              v = l.substr(p + 1);
              boost::trim(v);
              int64_t r = boost::lexical_cast<int64_t>(v);
              r += step;
              pair_[k] = r;
            }
          }

          f.close();
          read_ = true;
        }

        return *this;
      }

      void save() {
        remove(file_.c_str());
        std::ofstream of(file_.c_str(), std::ios::out | std::ios::binary);
        map_string::const_iterator c_it = pair_.begin();
        for (; c_it!=pair_.end(); ++c_it)
          of << c_it->first << "=" << c_it->second << std::endl;

        of.clear();
        of.close();
      }
  };

}

